package work.chenxr.security.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import work.chenxr.security.properties.TokenProperties;

import java.io.Serial;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Author Chenxr
 * @Date 2023/10/23
 * @Description 令牌工具类
 */
@Slf4j
@Component
@AllArgsConstructor
public class TokenUtil {
    private TokenProperties tokenProperties;

    /**
     * 生成，这里生成后的令牌只用于校验登录，所以其中的的某些参数选择了忽略，请根据实际需求变更
     */
    public String generator() {
        Map<String, Object> header = new HashMap<>() {
            @Serial
            private static final long serialVersionUID = 1L;

            // 其中参数自己定义，这里只做示范
            {
                put("uid", UUID.randomUUID().toString());
                put("timestamp", System.currentTimeMillis());
            }
        };

        Map<String, Object> payload = new HashMap<>() {
            @Serial
            private static final long serialVersionUID = 1L;

            // 其中参数自己定义，这里只做示范
            {
                put("uid", UUID.randomUUID().toString());
                put("timestamp", System.currentTimeMillis());
            }
        };

        // 注：因为采用Redis存储令牌，所以这里不写入到期时间
        return this.getPrefix() + JWT.create().withHeader(header).withPayload(payload)
                .sign(Algorithm.HMAC256(tokenProperties.getTokenKey()));
    }

    /**
     * 校验
     *
     * @param token 令牌
     */
    public boolean verify(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(tokenProperties.getTokenKey());
            JWTVerifier jwtVerifier = JWT.require(algorithm).build();
            jwtVerifier.verify(StringUtils.replace(token, this.getPrefix(), StringUtils.EMPTY));
        } catch (IllegalArgumentException | JWTVerificationException e) {
            log.error("令牌解析错误，错误原因:：{}", e.getLocalizedMessage());
            return false;
        }
        return true;
    }

    /**
     * 从请求中获取
     */
    public String get(HttpServletRequest request) {
        String accessToken = request.getHeader("Authorization");
        if (StringUtils.isBlank(accessToken)) {
            accessToken = request.getParameter("access_token");
        }
        return accessToken;
    }

    /**
     * 获取令牌前缀
     */
    private String getPrefix() {
        return tokenProperties.getTokenPrefix() + StringUtils.SPACE;
    }
}
